package com.sodaopen.study.utils;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import javax.imageio.ImageIO;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class ImageUtils {


	/**
	 * 压缩图片的宽高
	 * @param source
	 * @param targetW
	 * @param targetH
	 * @return
	 */
	private static BufferedImage resize(BufferedImage source, int targetW, int targetH) {    
        // targetW，targetH分别表示目标长和宽    
        int type = source.getType();    
        BufferedImage target = null;    
        double sx = (double) targetW / source.getWidth();    
        double sy = (double) targetH / source.getHeight();    
        // 这里想实现在targetW，targetH范围内实现等比缩放。如果不需要等比缩放    
        // 则将下面的if else语句注释即可    
        if (sx < sy) {  
            sy = sx;    
            targetH = (int) (sx * source.getHeight());              
        } else {    
            sx = sy;    
            targetW = (int) (sy * source.getWidth()); 
        }    
        if (type == BufferedImage.TYPE_CUSTOM) { // handmade    
            ColorModel cm = source.getColorModel();    
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW,   
                    targetH);    
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();    
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);   
        } else   
            target = new BufferedImage(targetW, targetH, type);    
        Graphics2D g = target.createGraphics();    
        // smoother than exlax:    
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,    
                RenderingHints.VALUE_INTERPOLATION_BICUBIC);    
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));   
        g.dispose();    
        return target;    
    }  
	
	
	
	/** 根据坐标裁剪图片
     * @param sourceFilePath 要裁剪的图片地址
     * @param targetFilePath 图片保存地址
     * @param startX 左上角X轴坐标
     * @param startY 左上角Y轴坐标
     * @param endX 右下角X轴坐标
     * @param endY 右下角Y轴坐标
     * @return
     */
    public static void cutImage(String sourceFilePath, String targetFilePath, int startX, int startY, int endX, int endY) throws IOException {
        cutImage(new File(sourceFilePath), targetFilePath, startX, startY, endX, endY);
    }

	/** 根据坐标裁剪图片
	 * @param file 要裁剪的图片文件
	 * @param targetFilePath 图片保存地址
	 * @param startX 左上角X轴坐标
	 * @param startY 左上角Y轴坐标
	 * @param endX 右下角X轴坐标
	 * @param endY 右下角Y轴坐标
	 * @return
	 */
	public static void cutImage(File file, String targetFilePath, int startX, int startY, int endX, int endY) throws IOException {
		BufferedImage sourceImage = ImageIO.read(file);
		sourceImage = resize(sourceImage, 400, 400);  //这里先转换成固定的400*400宽高，和页面的截图一致
		cutImage(sourceImage, targetFilePath, startX, startY, endX, endY);
	}

	/** 根据坐标裁剪图片
	 * @param sourceImage 要裁剪的图像
	 * @param targetFilePath 图片保存地址
	 * @param startX 左上角X轴坐标
	 * @param startY 左上角Y轴坐标
	 * @param endX 右下角X轴坐标
	 * @param endY 右下角Y轴坐标
	 * @return
	 */
	public static void cutImage(BufferedImage sourceImage, String targetFilePath, int startX, int startY, int endX, int endY) {
		BufferedImage result = cutImage(sourceImage, startX, startY, endX, endY);
		try {
			String suffixName = getSuffixName(targetFilePath);

			File targetFile = new File(targetFilePath);
			if (!targetFile.getParentFile().exists()) {
				targetFile.getParentFile().mkdirs();// 新建文件夹
            }
			ImageIO.write(result, suffixName, new FileOutputStream(targetFile));

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/** 根据坐标裁剪图片
	 * @param sourceImage 要裁剪的图像
	 * @param startX 左上角X轴坐标
	 * @param startY 左上角Y轴坐标
	 * @param endX 右下角X轴坐标
	 * @param endY 右下角Y轴坐标
	 * @return
	 */
	public static BufferedImage cutImage(BufferedImage sourceImage, int startX, int startY, int endX, int endY) {
	    if (sourceImage == null) {
            throw new RuntimeException("图片信息为空");
        }
		int width = sourceImage.getWidth();
		int height = sourceImage.getHeight();
		if (startX == -1) {
			startX = 0;
		}
		if (startY == -1) {
			startY = 0;
		}
		if (endX == -1) {
			endX = width - 1;
		}
		if (endY == -1) {
			endY = height - 1;
		}
		BufferedImage result = new BufferedImage(endX - startX, endY - startY, 4);
		for (int x = startX; x < endX; ++x) {
			for (int y = startY; y < endY; ++y) {
				int rgb = sourceImage.getRGB(x, y);
				result.setRGB(x - startX, y - startY, rgb);
			}
		}
		return result;
	}

	/** 根据坐标裁剪Base64图片
	 * @param base64string 要裁剪的图片Base64字符串
	 * @param suffixName 后缀名
	 * @param startX 左上角X轴坐标
	 * @param startY 左上角Y轴坐标
	 * @param endX 右下角X轴坐标
	 * @param endY 右下角Y轴坐标
	 * @return
	 */
	public static String cutBase64Image(String base64string, String suffixName, int startX, int startY, int endX, int endY) {
		// base64转bufferedImage
		BufferedImage bufferedImage = getBufferedImage(base64string);
		BufferedImage result = cutImage(bufferedImage, startX, startY, endX, endY);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();// io流
		try {
			ImageIO.write(result, suffixName, baos);
			// 写入流中
			byte[] bytes = baos.toByteArray(); // 转换成字节
			BASE64Encoder encoder = new BASE64Encoder();
			String img_base64 = encoder.encodeBuffer(bytes).trim(); // 转换成base64串
			img_base64 = img_base64.replaceAll("\n", "").replaceAll("\r", ""); // 删除 \r\n
			// 前面拼上前缀
			img_base64 = "data:image/"+suffixName+";base64,"+img_base64;
			return img_base64;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}

	/** base64String 转 BufferedImage
	 * @param base64string
	 * @return BufferedImage
	 */
	public static BufferedImage getBufferedImage(String base64string) {
		BufferedImage image = null;
		try {
			InputStream stream = baseToInputStream(base64string);
			image = ImageIO.read(stream);
			System.out.println(">>>" + image.getWidth() + "," + image.getHeight() + "<<<");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return image;
	}

	/**
	 * base64string 转 inputStream
	 * @param base64string
	 * @return
	 */
	public static InputStream baseToInputStream(String base64string) {
		ByteArrayInputStream stream = null;
		try {
			BASE64Decoder decoder = new BASE64Decoder();
			byte[] bytes1 = decoder.decodeBuffer(base64string);
			stream = new ByteArrayInputStream(bytes1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return stream;
	}

	/**
	 * 获取图片后缀名
	 * @param fileName 文件名
	 * @return
	 */
	public static String getSuffixName(String fileName) {
		// ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
		String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
		String suffix = null;
		// 获取图片后缀
		if(fileName.contains(".")) {
			suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
		}
		// 类型和图片后缀全部小写，然后判断后缀是否合法
		if(suffix == null || suffix.trim().length() == 0 || !types.toLowerCase().contains(suffix.toLowerCase() + ",")){
			throw new RuntimeException("Sorry, the image suffix [" + suffix + "] is illegal. the standard image suffix is {}." + types);
		}
		return suffix;
	}


}
